from decimal import Decimal

from django.db import transaction
from django.utils import timezone
from rest_framework import serializers

from goods.models import SKU
from django_redis import get_redis_connection


class CartSKUSerializer(serializers.ModelSerializer):
    """
    购物车商品数据序列化器
    """
    count = serializers.IntegerField(label='数量')

    class Meta:
        model = SKU
        fields = ('id', 'name', 'default_image_url', 'price', 'count')


class OrderSettlementSerializer(serializers.Serializer):
    """
    订单结算数据序列化器
    """
    freight = serializers.DecimalField(label='运费', max_digits=10, decimal_places=2)
    skus = CartSKUSerializer(many=True)


from orders.models import OrderInfo, OrderGoods


class OrderCommitSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }

    def create(self, validated_data):
        """保存订单"""
        """
        # 1.获取用户信息
        # 2.生成订单编号
        # 3.获取address和pay_method
        # 4.保存基本订单信息
        # 5.获取redis里的数据
        # # 判断库存是否充足
        # # 增加销量,减少库存
        # 6.保存订单信息
        # 7.删除redis里的数据
        # 8.返回数据
        """
        # 1.获取用户信息
        user = self.context['request'].user
        # 2.生成订单编号
        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
        # 3.获取address和pay_method以及订单状态
        address = validated_data['address']
        pay_method = validated_data['pay_method']
        if OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        # 4.保存基本订单信息
        with transaction.atomic():
            # 创建一个保存点
            save_id = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=status
                )
                # 5.获取redis里的数据
                redis_conn = get_redis_connection('cart')
                redis_cart = redis_conn.hgetall('cart_%s' % user.id)
                redis_seleted_ids = redis_conn.smembers('cart_selected_%s' % user.id)
                # cart={}
                for id in redis_seleted_ids:
                    count = int(redis_cart[id])
                    # cart[int(id)]=int(count)
                    sku = SKU.objects.get(pk=id)
                    # # 判断库存是否充足
                    if count > sku.stock:
                        raise serializers.ValidationError('库存不足')
                    # # 增加销量,减少库存
                    # sku.sales += count
                    # sku.stock -= count
                    origin_stock = sku.stock
                    origin_sales = sku.sales
                    new_stock = origin_stock - count
                    new_sales = origin_sales + count
                    SKU.objects.filter(id=sku.id,stock=origin_stock ).update(stock=new_stock,
                                                                           sales=new_sales)

                    # 6.修改及保存订单信息
                    order.total_count += count
                    order.total_amount += count * sku.price

                    OrderGoods.objects.create(
                        sku=sku,
                        order=order,
                        count=count,
                        price=sku.price
                    )
                order.save()
            except ValueError:
                raise
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError('下单失败')
            # 提交事务
            transaction.savepoint_commit(save_id)
            # 7.删除redis里的数据
            redis_conn.hdel('cart_%s' % user.id, *redis_seleted_ids)
            redis_conn.srem('cart_selected_%s' % user.id, *redis_seleted_ids)
            # 8.返回数据
            return order
